package com.molichuxing.gateway.bff.permission.services.impl;

import com.molichuxing.framework.dto.Paged;
import com.molichuxing.framework.result.ResponseCodeEnum;
import com.molichuxing.framework.result.ResponseResult;
import com.molichuxing.framework.utils.CollectionUtils;
import com.molichuxing.framework.utils.StringUtil;
import com.molichuxing.gateway.bff.permission.convertor.Convert;
import com.molichuxing.gateway.bff.permission.entity.request.GroupBindVo;
import com.molichuxing.gateway.bff.permission.entity.request.GroupCreateVo;
import com.molichuxing.gateway.bff.permission.entity.request.GroupModifyVo;
import com.molichuxing.gateway.bff.permission.entity.response.GroupBindResourceVo;
import com.molichuxing.gateway.bff.permission.entity.response.GroupVo;
import com.molichuxing.gateway.bff.permission.services.GroupBffService;
import com.molichuxing.gateway.utils.RedisPermissionUtil;
import com.molichuxing.gateway.utils.RequestAttrUtil;
import com.molichuxing.gateway.utils.TokenUtil;
import com.molichuxing.gateway.utils.entity.UserEntity;
import com.molichuxing.services.business.service.GroupBizService;
import com.molichuxing.services.infrastructure.dto.response.DealerDto;
import com.molichuxing.services.infrastructure.dto.response.IovGroupBindResourceDto;
import com.molichuxing.services.infrastructure.dto.response.response.*;
import com.molichuxing.services.infrastructure.service.*;
import com.molichuxing.services.property.GroupSystemTypeEnum;
import com.molichuxing.services.property.StatusEnum;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.*;

@Service("permissionGroupBffService")
public class GroupBffServiceImpl implements GroupBffService {

    private static final Logger logger = LoggerFactory.getLogger(AccountBffServiceImpl.class);

    @Resource
    private GroupBizService groupBizService;

    @Resource
    private DealerService dealerService;

    @Resource
    private GroupService groupService;

    @Resource
    private TokenUtil tokenUtil;

    @Resource
    private AccountGroupService accountGroupService;

    @Resource
    private AccountService accountService;

    @Resource
    private GroupResourceService groupResourceService;

    @Resource
    private ResourceService resourceService;

    @Resource
    private RedisPermissionUtil redisPermissionUtil;


    @Override
    public ResponseResult<Paged<GroupVo>> getGroupList(Map<String, Object> param, int pageNum, int pageSize) {
        Integer dealerId = RequestAttrUtil.getCurrentDealerId(); //当前登陆用户的经销商id

        param.put("groupSystemType", GroupSystemTypeEnum.DEALER.getValue());
        param.put("dealerId", dealerId);

        ResponseResult<Paged<GroupVo>> result = new ResponseResult<Paged<GroupVo>>();
        Paged<GroupVo> data = new Paged<>();

        Paged<GroupDto> pageList = groupBizService.getGroupPageList(param, pageNum, pageSize);
        if (pageList != null && CollectionUtils.isNotEmpty(pageList.getList())) {
             List<GroupVo> groupList = Convert.toGroupVoList(pageList.getList());
            final Set<Integer> dealerIdSet = new HashSet<>();
            groupList.forEach(group -> {
                if (group.getDealerId() != null && group.getDealerId() > 0) {
                    dealerIdSet.add(group.getDealerId());
                }
            });

            if (CollectionUtils.isNotEmpty(dealerIdSet)) {
                Map<String, Object> getDealerParam = new HashMap<>();
                getDealerParam.put("dealerIds", dealerIdSet);
                List<DealerDto> dealerList = dealerService.getDealerListByParam(getDealerParam);  //查询经销商

                final Map<Integer, String> dealerMap = new HashMap();
                dealerList.forEach(dealer -> {
                    dealerMap.put(dealer.getDealerId(), dealer.getShortName());
                });

                if (dealerMap != null && dealerMap.size() > 0) {
                    groupList.forEach(group -> {
                        group.setDealerName(dealerMap.get(group.getDealerId())); //为角色赋值
                    });
                }
            }
            data.setList(groupList);
            data.setTotal(pageList.getTotal());
            data.setPageSize(pageList.getPageSize());
        }
        return result.success("成功", data);
    }


    @Override
    public ResponseResult<Boolean> createGroup(GroupCreateVo vo) {
        Integer dealerId = RequestAttrUtil.getCurrentDealerId(); //当前登陆用户的经销商id

        ResponseResult<Boolean> result = new ResponseResult<>();
        if (vo == null)
            return result.error("角色不能为空", Boolean.FALSE);
        if (StringUtil.isEmpty(vo.getGroupName()))
            return result.error("角色名称不能为空", Boolean.FALSE);
        if (StringUtil.isEmpty(vo.getGroupDesc()))
            return result.error("角色描述不能为空", Boolean.FALSE);

        try {
            //groupName要求唯一性，如果在op，则同一系统中不允许出现同名角色，如果是经销商系统，则同一经销商下不允许有同名角色
            GroupDto currentNameGroup = groupService.getGroupByNameAndDealerId(GroupSystemTypeEnum.DEALER.getValue(), dealerId, vo.getGroupName());
            if (currentNameGroup != null)
                return result.error("【" + vo.getGroupName() + "】已存在，不允许重复录入", Boolean.FALSE);

            GroupCreateDto dto = Convert.toGroupCreateDto(vo);

            UserEntity currentLoginUser = tokenUtil.getUser();

            dto.setOperatorAccountId(currentLoginUser.getAccountId()); //操作人id
            dto.setOperatorAccount(currentLoginUser.getRealName()); //操作人姓名
            dto.setDealerId(dealerId);

            int id = groupService.createGroup(dto);
            if (id > 0)
                return result.success("添加成功", Boolean.TRUE);
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
        }
        return result.error("添加失败", Boolean.FALSE);
    }

    @Override
    public ResponseResult<Boolean> modifyGroup(GroupModifyVo vo) {
        Integer dealerId = RequestAttrUtil.getCurrentDealerId(); //当前登陆用户的经销商id

        ResponseResult<Boolean> result = new ResponseResult<>();
        if (vo == null)
            return result.error("角色不能为空", Boolean.FALSE);
        if (vo.getId() == null || vo.getId() <= 0)
            return result.error("用户id不能为空", Boolean.FALSE);

        //车联网需要调用车联网修改角色接口，op本地库不存车联网数据
        try {
            //获取用角色
            GroupDto oldGroup = groupService.getGroupById(vo.getId());
            if (oldGroup == null) //数据库中没有此用户
                return result.error("角色不存在，修改失败");

            //检查在相同机构下（如果是op就同一类型下）是否存在同名角色，如果存在，提示保存失败
            GroupDto currentNameGroup = groupService.getGroupByNameAndDealerId(GroupSystemTypeEnum.DEALER.getValue(), dealerId, vo.getGroupName());
            if (currentNameGroup != null && currentNameGroup.getId() != vo.getId())
                return result.error("【" + vo.getGroupName() + "】" + "已存在，不允许重复录入", Boolean.FALSE);

            GroupModifyDto dto = Convert.toGroupModifyDto(vo);

            UserEntity currentLoginUser = tokenUtil.getUser();

            dto.setOperatorAccountId(currentLoginUser.getAccountId()); //操作人id
            dto.setOperatorAccount(currentLoginUser.getRealName()); //操作人姓名

            int row = groupService.modifyGroup(dto);
            if (row > 0) { //修改完成后, 与此角色关联的用户全部强制登出
                Map<String, Object> getAccountGroupParam = new HashMap<>();
                getAccountGroupParam.put("groupId", dto.getId());

                List<AccountGroupDto> accountGroupList = accountGroupService.getAccountGroupListByParam(getAccountGroupParam);
                if (CollectionUtils.isNotEmpty(accountGroupList)) {
                    final List<Integer> accountIds = new ArrayList<>();
                    accountGroupList.forEach(accountGroup -> {
                        accountIds.add(accountGroup.getAccountId());
                    });

                    Map<String, Object> getAccountParam = new HashMap<>();
                    getAccountParam.put("ids", accountIds);
                    List<AccountDto> accountList = accountService.getAccountByParam(getAccountParam);
                    accountList.forEach(account -> {  //强制登出
                        tokenUtil.deleteUserByAccount(account.getAccount());
                    });

                    if (dto.getStatus() == StatusEnum.OFF.getValue()) { //角色被禁用，删除用户与角色的关联关系
                        Map<String, Object> deleteAccountGroupParam = new HashMap<>();
                        deleteAccountGroupParam.put("groupId", dto.getId());
                        accountGroupService.deleteByParam(deleteAccountGroupParam); //删除用户与角色的关联关系
                    }

                }

                if (dto.getStatus() == StatusEnum.OPEN.getValue()) { //重写redis
                    redisPermissionUtil.resourceToRedis(oldGroup.getId());
                } else { //删除redis数据
                    redisPermissionUtil.deleteResourceByGroupId(oldGroup.getId());
                }
            }
            return result.success("修改成功", Boolean.TRUE);
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
        }
        return result.error("修改失败", Boolean.FALSE);
    }

    @Override
    public List<GroupVo> getGroupListInModifyAccountPage() throws Exception {
        Integer dealerId = RequestAttrUtil.getCurrentDealerId(); //当前登陆用户的经销商id

        List<GroupVo> result = new ArrayList<>();
        if (dealerId <= 0) {
            throw new IllegalArgumentException("dealerId INVAILD");
        }
        Map<String, Object> getGroupParam = new HashMap<>();
        getGroupParam.put("groupSystemType", GroupSystemTypeEnum.DEALER.getValue());
        getGroupParam.put("dealerId", dealerId);
        return Convert.toGroupVoList(groupService.getGroupListByParm(getGroupParam));
    }

    @Override
    public GroupBindResourceVo getPermissionTree(int groupId) {
        GroupBindResourceVo result = new GroupBindResourceVo();

        try {
            Map<String, Object> getGroupResourceParam = new HashMap<>();
            getGroupResourceParam.put("groupId", groupId);

            //将绑定的权限id放进集合
            final List<Integer> bindResourceIdList = new ArrayList<>();
            List<GroupResourceDto> groupResourceList = groupResourceService.getGroupResourceListByParm(getGroupResourceParam);
            if (CollectionUtils.isNotEmpty(groupResourceList)) {
                groupResourceList.forEach(groupResourceDto -> {
                    bindResourceIdList.add(groupResourceDto.getResourceId());
                });
            }

            List<ResourceDto> resourceTree = resourceService.getResoureTree(GroupSystemTypeEnum.DEALER.getValue());

            result.setGroupBindpermissionIds(bindResourceIdList);
            result.setPermissionTree(resourceTree);
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
        }
        return result;
    }

    /**
     * 创建角色与权限的关联（先删除后添加，如果resourceIds为null则只删除不添加）

     * @return
     */
    public ResponseResult<Boolean> createBatchGroupResource(GroupBindVo vo) {
        ResponseResult<Boolean> result = new ResponseResult<>();
        if (vo.getGroupId() <= 0)
            return result.error("角色id不能为kong", Boolean.FALSE);

        try {
            groupBizService.createBatchGroupResource(vo.getGroupId(), vo.getDataIds());

            Map<String, Object> getAccountGroupParam = new HashMap<>();
            getAccountGroupParam.put("groupId", vo.getGroupId());

            List<AccountGroupDto> accountGroupList = accountGroupService.getAccountGroupListByParam(getAccountGroupParam);
            if (CollectionUtils.isNotEmpty(accountGroupList)) {
                final List<Integer> accountIds = new ArrayList<>();
                accountGroupList.forEach(accountGroup -> {
                    accountIds.add(accountGroup.getAccountId());
                });

                Map<String, Object> getAccountParam = new HashMap<>();
                getAccountParam.put("ids", accountIds);
                List<AccountDto> accountList = accountService.getAccountByParam(getAccountParam);
                accountList.forEach(account -> {  //强制登出
                    tokenUtil.deleteUserByAccount(account.getAccount());
                });
            }

            //重写redis中的权限
            redisPermissionUtil.resourceToRedis(vo.getGroupId());

            return result.success("成功", Boolean.TRUE);
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
        }

        return result.error("失败", Boolean.FALSE);
    }
}
